from typing import Optional, Union
from django.conf import ImproperlyConfigured
from django.views.generic.base import ContextMixin

from .. import models
from .. import forms

class AuditorContextMixin(ContextMixin):
    """
    NOTE Use it with views that provide 'object' in context.
    Note that MRO order.
    """
    audit_permission: Union[str, list[str], None] = None
    use_audit_form: bool = True
    audit_form_fields: list[str] = ['comment', 'status']
    audit_form_action: Optional[str] = None

    def get_audit_permission_required(self):
        """
        Override this method to override the permission_required attribute.
        Must return an iterable.
        """
        if self.audit_permission is None:
            raise ImproperlyConfigured(
                f"{self.__class__.__name__} is missing the "
                f"audit_permission attribute. Define "
                f"{self.__class__.__name__}.audit_permission, or override "
                f"{self.__class__.__name__}.get_audit_permission_required()."
            )
        if isinstance(self.audit_permission, str):
            perms = (self.audit_permission,)
        else:
            perms = self.audit_permission
        return perms

    
    def get_context_data(self, **kwargs):
        user = self.request.user
        context = super().get_context_data(**kwargs)
        if 'object' not in context:
            raise ImproperlyConfigured(
                f"{self.__class__.__name__} doesn't provide 'object' in context."
            )
        object = context['object']
        am = models.AuditManagement.objects.get_for_object(object)

        context.update({
            'am': am,
            'can_audit': user.has_perm(self.get_audit_permission_required())
        })

        if self.use_audit_form:
            
            AuditFormClass = forms.create_audit_form(
                form_action = self.get_audit_form_action(),
                form_fields = self.audit_form_fields
            )
            context['audit_form'] = AuditFormClass(instance=am)

        return context

    def get_audit_form_action(self):
        return self.audit_form_action
